#include <iostream>
#include <string.h>

using std::cout;
using std::endl;

class String{
public:
    String()
    : _pstr(nullptr) 
    {
        cout<<"String()"<<endl;
    }
    String(const char *pstr)
    : _pstr(new char[strlen(pstr)+1]())
    {
        strcpy(_pstr,pstr);
        cout<<"String(const char *pstr)"<<endl;
    }
    
    String(const String &rhs)
    : _pstr(new char[strlen(rhs._pstr)+1]())
    {
        cout<<"String(const String &rhs)"<<endl;
        strcpy(_pstr,rhs._pstr);
    }

    String &operator=(const String &rhs)
    {
        cout<<"String &operator=(const String &rhs)"<<endl;
        if(this!=&rhs){
            delete []_pstr;
            _pstr=nullptr;

            _pstr=new char[strlen(rhs._pstr)+1]();
            strcpy(_pstr,rhs._pstr);
        }
        return *this;
    }

    //移动构造函数
    String(String &&rhs)
    : _pstr(rhs._pstr)  //直接把s1的指针指向右值申请出来的空间
    {
        cout<<"String(String &&rhs)"<<endl;
        rhs._pstr=nullptr;  //防止临时对象释放时，带走那片空间
    }

    ~String(){
        cout<<"~String()"<<endl;
        if(_pstr){
            delete []_pstr;
            _pstr=nullptr;
        }
    }

    friend std::ostream &operator<<(std::ostream &os, const String &rhs);

private:
    char *_pstr;
};
std::ostream &operator<<(std::ostream &os, const String &rhs){
    if(rhs._pstr){
        os<<rhs._pstr;
    }
    return os;
}

void test(){
    String s1("hello");
    cout<<"s1="<<s1<<endl;

    cout<<endl;
    String s2=s1;
    String s4(s1);
    cout<<"s2="<<s2<<endl;

    cout<<endl;
    String s3("world");
    s3=s1;
    cout<<"s3="<<s3<<endl;
}

void test2(){
    //c风格字符串---隐式转换---》c++风格字符串
    //先根据“hello”，调用构造函数String(const char *pstr)创建临时对象String("hello")
    //然后用临时对象给s1拷贝构造，然后马上释放临时对象
    //这样频繁申请释放堆空间，产生内存碎片
    //可以把 s1的指针 指向 临时对象申请出来的空间，这样少申请释放一次堆空间
    String s1="hello";  //隐式转换，先有String("hello")临时对象，然后移动构造函数
}

int main()
{   
    test2();
    return 0;
}

